package itsm.isperp.framework.web.controller;

import itsm.isperp.framework.data.domain.PageResponse;
import itsm.isperp.framework.domain.IBean;
import itsm.isperp.framework.service.BaseService;
import itsm.isperp.framework.utils.HibernateUUIDGenerator;
import itsm.isperp.framework.web.domain.CountQuery;
import itsm.isperp.framework.web.formatter.StringEscapeEditor;
import itsm.isperp.framework.web.request.JqGridFilterRuleOp;
import itsm.isperp.framework.web.request.JqGridRequest;
import itsm.isperp.framework.web.response.ResultMessage;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

/**
 * 基础控制器，保护管理页面、编辑页面、保存操作、删除操作及导出excel操作
 * 
 * @author lizx
 * @date 2013-2-17
 * @version V1.0
 */
@ControllerAdvice
@Component
public abstract class BaseController<T extends IBean> {

	protected final Log logger = LogFactory.getLog(getClass());

	// @InitBinder
	// protected void initBinder(WebDataBinder binder) {
	// // binder.registerCustomEditor(Date.class, new DateEditor());
	// // binder.registerCustomEditor(Timestamp.class, new TimestampEditor());
	//
	// }

	//
	// @ExceptionHandler
	// public @ResponseBody
	// ResultMessage handle(Exception e) {
	// return ResultMessage.failure(e.getMessage());
	// }
	// @InitBinder
	// public void initBinder(WebDataBinder binder) {
	// binder.registerCustomEditor(String.class, new StringEscapeEditor(true,
	// true, true));
	// }

	/**
	 * 获取服务
	 * 
	 * @return 基础服务接口
	 */
	public abstract <U extends T> BaseService<U> getService();

	public CountQuery createDefaultCountQuery() {
		return getService().createDefaultCountQuery();
	}

	/**
	 * 获取页面的标题
	 * 
	 * @return 页面标题
	 */
	public abstract String getPageTitle();

	/**
	 * 获取模块的路径
	 * 
	 * @return 模块的路径
	 */
	protected String getModulePath() {
		return this.getClass().getAnnotation(RequestMapping.class).value()[0];
	}

	/**
	 * 管理界面
	 * 
	 * @return 菜单管理界面视图
	 */
	@RequestMapping(value = { "manage", "" })
	public ModelAndView manage(HttpServletRequest req) {
		return this.getModelAndView();
	}

	/**
	 * 编辑界面
	 * 
	 * @param id
	 *            唯一标识
	 * @return 编辑视图
	 */
	@RequestMapping("edit")
	public ModelAndView edit(String id, HttpServletRequest req)
			throws Exception {
		return this.getEdit(id);
	}

	/**
	 * 查看界面
	 * 
	 * @param id
	 *            唯一标识
	 * @param req
	 *            http请求
	 * @return 查看界面
	 */
	@RequestMapping("view")
	public ModelAndView view(String id, HttpServletRequest req) {
		ModelAndView mv = this.getModelAndView();
		mv.addObject("model", this.getService().findOne(id));
		return mv;
	}

	/**
	 * 保存实体,只会更新提交的表达中有包含的字段
	 * 
	 * @param model
	 *            　一个实现IBean接口的实体　{@link IBean}
	 * @param req
	 *            {@link HttpServletRequest} http请求
	 * @return json结果数据
	 */
	@RequestMapping("save")
	@ResponseBody
	public ResultMessage save(T model, HttpServletRequest req) {


		this.getService().saveOrUpdate(model, req);
		ResultMessage res = ResultMessage.newInstance(true, null, model.getId());
		return res;
	}

	@RequestMapping("getOne")
	@ResponseBody
	public T getOne(String id, HttpServletRequest req) {

		if (StringUtils.isEmpty(id)) {
			return null;
		}

		String displayColumn = req.getParameter("displayColumn");
		JqGridRequest request = new JqGridRequest();
		request.addFilterRule("id", JqGridFilterRuleOp.eq, id);
		if (StringUtils.isNotEmpty(displayColumn))
			request.setSelectColumns(displayColumn);

		return this.getService().findOneByRequest(request);
	}

	/**
	 * 根据唯一标识删除实体
	 * 
	 * @param id
	 *            唯一标识
	 * @param req
	 *            {@link HttpServletRequest} http请求
	 * @return 删除结果
	 */
	@RequestMapping("delete")
	@ResponseBody
	public ResultMessage delete(String id, HttpServletRequest req) {

		this.getService().delete(id);

		return ResultMessage.newInstance(true);
	}

	/**
	 * 根据分页器获取实体列表的json格式数据
	 * 
	 * @param request
	 *            {@link JqGridRequest} jqGrid数据请求（查询条件、排序）
	 * @param req
	 *            {@link HttpServletRequest} http请求
	 * @return json格式数据
	 */
	@RequestMapping("list")
	@ResponseBody
	public PageResponse<T> list(JqGridRequest request, HttpServletRequest req) {
		return this.getService().findAll(request).toPage();

	}

	/**
	 * 详细信息列表
	 * 
	 * @param request
	 * @param req
	 * @return
	 */
	@RequestMapping("listDetail")
	@ResponseBody
	public PageResponse<Map<String, Object>> listDetail(JqGridRequest request,
			HttpServletRequest req) {
		return this.getService().findAllDetailByRequest(request).toPage();

	}

	protected PageResponse<T> getList(CountQuery cq, JqGridRequest request,
			HttpServletRequest req) {
		String queryPath = req.getParameter("queryPath");

		if (cq != null) {
			request.setCountQuery(cq);
			request.setQueryPath(queryPath);

		}
		return this.getService().findAll(request).toPage();
	}

	protected PageResponse<Map<String, Object>> getListDetail(CountQuery cq,
			JqGridRequest request, HttpServletRequest req) {
		String queryPath = req.getParameter("queryPath");

		if (cq != null) {
			request.setCountQuery(cq);
			request.setQueryPath(queryPath);

		}
		return this.getService().findAllDetailByRequest(request).toPage();
	}

	/**
	 * 获取单一实体
	 * 
	 * @param id
	 *            唯一标识
	 * @return 实体的json格式数据
	 */
	@RequestMapping("get")
	@ResponseBody
	public T get(String id) {
		return this.getService().findOne(id);
	}

	/**
	 * 获取一个模型及视图 {@link ModelAndView},其路径为控制器标记的路径加方法名
	 * 
	 * @return 模型及视图 {@link ModelAndView}
	 */
	protected ModelAndView getModelAndView() {

		ModelAndView mv = new ModelAndView(this.getModulePath() + "/"
				+ Thread.currentThread().getStackTrace()[2].getMethodName());
		mv.addObject("pageTitle", this.getPageTitle());
		return mv;
	}

	/**
	 * 获取一个编辑模型及视图 {@link ModelAndView}
	 * 
	 * @param id
	 *            唯一标识
	 * @return 模型及视图 {@link ModelAndView}
	 */
	protected ModelAndView getEdit(String id) {
		ModelAndView mv = new ModelAndView();

		// TODO 由于采用放射的方式进行
		if (StringUtils.isEmpty(id)) {
			Type genType = getClass().getGenericSuperclass();
			Type[] params = ((ParameterizedType) genType)
					.getActualTypeArguments();
			try {
				Class<?> cls = ((Class<?>) params[0]);

				@SuppressWarnings("unchecked")
				T model = (T) cls.newInstance();
				model.setId(HibernateUUIDGenerator.generate());
				try {
					Field f = cls.getField("orderNum");
					Long c = this.getService().findAllCount(null);
					f.setAccessible(true);
					f.setInt(model, c.intValue());
				} catch (Exception e) {
					// do nothing
				}
				mv.addObject("model", model);
			} catch (Exception e) {
				throw new RuntimeException("实例化实体失败");
			}
		} else {
			T model = this.getService().findOne(id);
			mv.addObject("model", model);
		}
		mv.addObject("pageTitle", this.getPageTitle());

		mv.setViewName(this.getModulePath() + "/edit");
		return mv;
	}

}
